package com.dldata.devtools30.controller.sysform;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dldata.devtools30.common.EnumUtils;
import com.dldata.devtools30.entity.DevtFormDesignEntity;
import com.dldata.devtools30.entity.DevtFormMetadataEntity;
import com.dldata.devtools30.entity.DevtModelMetadataFieldEntity;
import com.dldata.devtools30.entity.DevtModelMetadataTableEntity;
import com.dldata.devtools30.repository.metadata.DevtModelMetadataTableDao;
import com.dldata.devtools30.repository.sysform.DevtFormMetadataDao;
import com.dldata.devtools30.service.metadata.DevtModelMetadataFieldService;
import com.dldata.devtools30.service.sysform.DevtFormDesignEntityService;
import com.dldata.devtools30.utils.StringUtil;
import com.dldata.devtools30.utils.Util;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping(value = "/V_DevtFormDesignEntityController")
@Slf4j
public class V_DevtFormDesignEntityController {
    
    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    DevtFormMetadataDao sysCrfFormMetadataDao;
    @Autowired
    DevtModelMetadataTableDao metadataTableDao;
    @Autowired
    DevtFormDesignEntityService formDesignService;
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    DevtModelMetadataFieldService metadataFieldService;

    @RequestMapping("toPage")
    public String toSysFormTypeList(String pid, Model model){
        model.addAttribute("pid",pid);

        List<DevtFormDesignEntity> formDesignEntityList = formDesignService.getFormDesignDataByTempid(pid);

        model.addAttribute("loadFormJson",formDesignEntityList.size()>0? StringUtil.escape(formDesignEntityList.get(0).getJsonOpt()):"");
        return "thymeleaf/devtools30/sysform/v_SysFormDesign";
    }

    @RequestMapping("toChoseTableAndFieldPage")
    public String toChoseTableAndFieldPage(String tempid,Model model){
        List<DevtModelMetadataTableEntity> metadataTableEntities = metadataTableDao.getAll();

        model.addAttribute("tableList", metadataTableEntities);
        model.addAttribute("tableJsonStr", StringUtil.escape(JSON.toJSONString(metadataTableEntities)));
        model.addAttribute("tempid", tempid);
        return "thymeleaf/devtools30/sysform/v_FormDesignChoseTableAndFiled";
    }

    @RequestMapping("/saveAndUpdatePreview")
    public String saveAndUpdatePreview(@RequestParam Map paramp, Model model,HttpServletRequest request,HttpServletResponse httpServletResponse){
        String key = StrUtil.isEmpty(request.getParameter("softkey")) ? "" : String.format("&softkey=%s",request.getParameter("softkey"));
        key = key + (StrUtil.isEmpty(request.getParameter("biqtuser")) ? "" : String.format("&biqtuser=%s",request.getParameter("biqtuser")));
        request.setAttribute("bitoken",key);
        if(StrUtil.isEmpty((CharSequence)request.getAttribute("bitoken"))){
            request.setAttribute("bitoken","");
        }

        Map param=new LinkedCaseInsensitiveMap();
        param.putAll(paramp);
        String pageUrl="";
        if (StringUtil.isEmptyOrLength0(param.get("dataid"))){
            pageUrl=toPreview(param,model,request);
        }else {
            pageUrl=toPreviewUpdate(param,model,request,httpServletResponse);
        }
        return pageUrl;
    }


    public String toPreview(@RequestParam Map<String, Object> param, Model model,HttpServletRequest request){


        Map defaultValueMap = new LinkedCaseInsensitiveMap();
        Set paramKeySet = param.keySet();
        for (Object keyName : paramKeySet) {
            String [] arr=keyName.toString().split("_",2);
            if (arr[0].equalsIgnoreCase("mDefaultValue")){
                defaultValueMap.put(arr[1],param.get(keyName));
            }
        }

        if(StrUtil.isEmpty((CharSequence)param.get("tempid"))&&!StrUtil.isEmpty((CharSequence)request.getAttribute("tempid"))){
            param.put("tempid",(CharSequence)request.getAttribute("tempid"));
        }
        if(StrUtil.isEmpty((CharSequence)request.getAttribute("bitoken"))){
            request.setAttribute("bitoken","");
        }
        String tempid = param.get("tempid").toString();
        List<DevtFormDesignEntity> formDesignEntityList = formDesignService.getFormDesignDataByTempid(tempid);
        JSONObject JsonOpt = JSON.parseObject(formDesignEntityList.get(0).getJsonOpt());
        JSONArray list = JSONArray.parseArray(JsonOpt.get("list").toString());
        for (Object listMap : list) {
            Map patam = ((Map)listMap);
            if (patam.get("type").toString().equalsIgnoreCase("grid")){
                JSONArray gridList = JSONArray.parseArray(patam.get("columns").toString());
                for (Object gridListMap : gridList) {

                    JSONArray gridListMapArray =  JSONArray.parseArray(JSON.toJSONString(((Map)gridListMap).get("list")));
                    for (Object gridListMapArrayMap : gridListMapArray) {
                        Map gridMap = (Map) gridListMapArrayMap;

                        String sql = StringUtil.isEmptyOrLength0(gridMap.get("datasql")) ? "" : gridMap.get("datasql").toString();
                        JSONArray options = new JSONArray();

                        if (!StringUtil.isEmptyOrLength0(sql)) {
                            List<Map<String, Object>> resultList = jdbcTemplate.queryForList(FormatSql(sql,defaultValueMap,request));

                            resultList.stream().forEach(p -> {
                                Map map = new HashMap();
                                Set keySet = p.keySet();
                                if (keySet.size() == 1) {
                                    gridMap.put("defaultValue", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                                } else {
                                    map.put("value", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                                    map.put("label", StringUtil.isEmptyOrLength0(p.get("label"))?p.get("mc"):p.get("label"));
                                    map.put("tj", StringUtil.isEmptyOrLength0(p.get("tj"))?"":p.get("tj"));
                                    options.add(map);
                                }
                            });
                        }

                        if (!StringUtil.isEmptyOrLength0(gridMap.get("defaultValue"))){
                            gridMap.put("defaultValue",Util.replaceDefault(String.valueOf(gridMap.get("defaultValue")),request));
                        }
                        if (!StringUtil.isEmptyOrLength0(defaultValueMap.get(gridMap.get("id")))){
                            gridMap.put("defaultValue",defaultValueMap.get(gridMap.get("id")));
                        }

                        if (options.size()!=0){
                            gridMap.put("options", options);
                        }
                        ((Map) gridListMap).put("list",gridListMapArray);
                        patam.put("columns",gridList);
                    }
                }
            }else {
                String sql = StringUtil.isEmptyOrLength0(patam.get("datasql")) ? "" : patam.get("datasql").toString();
                JSONArray options = new JSONArray();
                if (!StringUtil.isEmptyOrLength0(sql)) {
                    List<Map<String, Object>> resultList = jdbcTemplate.queryForList(FormatSql(sql,defaultValueMap,request));
                    resultList.stream().forEach(p -> {
                        Map map = new HashMap();
                        Set keySet = p.keySet();
                        if (keySet.size() == 1) {
                            patam.put("defaultValue", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                        } else {
                            map.put("value", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                            map.put("label", StringUtil.isEmptyOrLength0(p.get("label"))?p.get("mc"):p.get("label"));
                            map.put("tj", StringUtil.isEmptyOrLength0(p.get("tj"))?"":p.get("tj"));
                            options.add(map);
                        }
                    });
                    patam.put("options", options);
                }
                
                if (!StringUtil.isEmptyOrLength0(patam.get("defaultValue"))){
                    patam.put("defaultValue",Util.replaceDefault(String.valueOf(patam.get("defaultValue")),request));
                }
                if (!StringUtil.isEmptyOrLength0(defaultValueMap.get(patam.get("id")))){
                    patam.put("defaultValue",defaultValueMap.get(patam.get("id")));
                }
                if (!StringUtil.isEmptyOrLength0(patam.get("defaultValue"))){
                    patam.put("defaultValue",Util.replaceDefault(String.valueOf(patam.get("defaultValue")) ,request));
                }
            }
        }
        JsonOpt.put("list",list);
        model.addAttribute("loadFormJson",formDesignEntityList.size()>0?StringUtil.escape(JSON.toJSONString(JsonOpt)):"");
        model.addAttribute("name",formDesignEntityList.size()>0?formDesignEntityList.get(0).getName():"");
        model.addAttribute("height",formDesignEntityList.size()>0?formDesignEntityList.get(0).getHeight():"");
        model.addAttribute("width",formDesignEntityList.size()>0?formDesignEntityList.get(0).getWidth():"");
        model.addAttribute("tempid",tempid);
        return "thymeleaf/devtools30/sysform/v_FormDesignPreview";
    }

    private String FormatSql(String sql,Map defaultValueMap,HttpServletRequest request){
        for (Object keyName : defaultValueMap.keySet()) {
            sql=sql.replaceAll("#"+keyName+"#",defaultValueMap.getOrDefault(keyName,"").toString());
        }
        sql= Util.replaceDefault(sql,request);
        return sql;
    }

    private String toPreviewUpdate(Map param, Model model, HttpServletRequest request, HttpServletResponse httpServletResponse){

        Map defaultValueMap = new LinkedCaseInsensitiveMap();
        Set paramKeySet = param.keySet();
        for (Object keyName : paramKeySet) {
            String [] arr=keyName.toString().split("_",2);
            if (arr[0].equalsIgnoreCase("mDefaultValue")){
                defaultValueMap.put(arr[1],param.get(keyName));
            }
        }

        List<DevtFormMetadataEntity> crfFormMetadataEntityList= sysCrfFormMetadataDao.getDataByTempleid(param.getOrDefault("tempid", "").toString());
        if(crfFormMetadataEntityList.size()==0){
            try {
                httpServletResponse.setContentType("text/html");
                httpServletResponse.setCharacterEncoding("UTF-8");
                httpServletResponse.getWriter().println("未绑定模型数据."+param.getOrDefault("tempid", "").toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        DevtModelMetadataTableEntity tableEntities= metadataTableDao.findById(crfFormMetadataEntityList.get(0).getTableid()).orElse(null);
        if(tableEntities==null){
            try {
                httpServletResponse.setContentType("text/html");
                httpServletResponse.setCharacterEncoding("UTF-8");
                httpServletResponse.getWriter().println("未绑定模型数据."+param.getOrDefault("tempid", "").toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /****************************第三方数据保存**********************************/
        String tableName =tableEntities.getStoretype().equalsIgnoreCase(EnumUtils.StoreTypeEnum.普通.name())?tableEntities.getCode():("v_"+tableEntities.getCode());
        String sql="select * from "+ tableName;
        sql=sql+" where "+ tableName +"."+"id"+"='"+param.get("dataid").toString()+"'";
        
        List<DevtModelMetadataFieldEntity> fieldEntityList = metadataFieldService.getAllByTid(tableEntities.getId());
        String sqlField="";
        for (DevtModelMetadataFieldEntity fieldEntity : fieldEntityList) {
            sqlField+= tableName +"."+fieldEntity.getFieldCode()+" "+ tableEntities.getCode() +"@"+fieldEntity.getFieldCode()+",";
        }
        if(sqlField.length()>0) {
            sqlField = sqlField.substring(0, sqlField.length() - 1);
            sql = sql.replace("*", sqlField);
        }
    
        Map resultMap = new LinkedCaseInsensitiveMap();
        resultMap.put(tableName+"@id",param.get("dataid").toString());
        try {
            log.info(sql);
            log.info(sqlField);
            List resultList = jdbcTemplate.queryForList(sql);
            if (resultList.size()>0){
                resultMap.putAll((Map) resultList.get(0));
            }
        }catch (Throwable throwable){
            log.error(throwable.getMessage(),throwable);
        }

        List<DevtFormDesignEntity> formDesignEntityList = formDesignService.getFormDesignDataByTempid(param.get("tempid").toString());
        JSONObject JsonOpt = JSON.parseObject(formDesignEntityList.get(0).getJsonOpt());
        JSONArray list = JSONArray.parseArray(JsonOpt.get("list").toString());
        for (Object listMap : list) {
            Map map = ((Map)listMap);

            if (map.get("type").toString().equalsIgnoreCase("grid")){
                JSONArray gridList = JSONArray.parseArray(map.get("columns").toString());
                for (Object gridListMap : gridList) {
                    JSONArray gridListMapArray =  JSONArray.parseArray(JSON.toJSONString(((Map)gridListMap).get("list")));
                    for (Object gridListMapArrayMap : gridListMapArray) {
                        Map gridMap = (Map) gridListMapArrayMap;

                        String datasql = StringUtil.isEmptyOrLength0(gridMap.get("datasql")) ? "" : gridMap.get("datasql").toString();
                        JSONArray options = new JSONArray();

                        if (!StringUtil.isEmptyOrLength0(datasql)) {
                            List<Map<String, Object>> result = jdbcTemplate.queryForList(FormatSql(datasql,defaultValueMap,request));
                            result.stream().forEach(p -> {
                                Map optionsMap = new HashMap();
                                Set keySet = p.keySet();
                                if (keySet.size() == 1) {
                                    gridMap.put("defaultValue", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                                } else {
                                    optionsMap.put("value", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                                    optionsMap.put("label", StringUtil.isEmptyOrLength0(p.get("label"))?p.get("mc"):p.get("label"));
                                    optionsMap.put("tj", StringUtil.isEmptyOrLength0(p.get("tj"))?"":p.get("tj"));
                                    options.add(optionsMap);
                                }
                            });
                        }
                        
                        if(!StrUtil.hasBlank(gridMap.get("id").toString())
                                &&!StringUtil.isEmptyOrLength0(resultMap.get(gridMap.get("id")))){
                            gridMap.put("defaultValue",FormatData(resultMap.get(gridMap.get("id"))));
                        }
                        if (!StringUtil.isEmptyOrLength0(gridMap.get("defaultValue"))){
                            gridMap.put("defaultValue",Util.replaceDefault(String.valueOf(gridMap.get("defaultValue")),request));
                        }
                        if (StringUtil.isEmptyOrLength0(gridMap.get("defaultValue"))){
                            if (!StringUtil.isEmptyOrLength0(defaultValueMap.get(gridMap.get("id")))){
                                gridMap.put("defaultValue",defaultValueMap.get(gridMap.get("id")));
                            }
                        }

                        if (options.size()!=0){
                            gridMap.put("options", options);
                        }
                        ((Map) gridListMap).put("list",gridListMapArray);
                        map.put("columns",gridList);
                    }
                }
            }else {
                if(StrUtil.hasBlank(map.get("id").toString())){
                    continue;
                }

                String datasql = StringUtil.isEmptyOrLength0(map.get("datasql")) ? "" : map.get("datasql").toString();
                JSONArray options = new JSONArray();
                if (!StringUtil.isEmptyOrLength0(datasql)) {
                    List<Map<String, Object>> resultList1 = jdbcTemplate.queryForList(FormatSql(datasql,defaultValueMap,request));
                    resultList1.stream().forEach(p -> {
                        Map map1 = new HashMap();
                        Set keySet = p.keySet();
                        if (keySet.size() == 1) {
                            map.put("defaultValue", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                        } else {
                            map1.put("value", StringUtil.isEmptyOrLength0(p.get("value"))?p.get("dm"):p.get("value"));
                            map1.put("label", StringUtil.isEmptyOrLength0(p.get("label"))?p.get("mc"):p.get("label"));
                            map1.put("tj", StringUtil.isEmptyOrLength0(p.get("tj"))?"":p.get("tj"));
                            options.add(map1);
                        }
                    });
                    map.put("options", options);
                }
                
                if(!StrUtil.hasBlank(map.get("id").toString())
                        &&!StringUtil.isEmptyOrLength0(resultMap.get(map.get("id")))){
                    map.put("defaultValue",FormatData(resultMap.get(map.get("id"))));
                }
                
                if (!StringUtil.isEmptyOrLength0(map.get("defaultValue"))){
                    map.put("defaultValue",Util.replaceDefault(String.valueOf(map.get("defaultValue")),request));
                }
                if (StringUtil.isEmptyOrLength0(map.get("defaultValue"))){
                    if (!StringUtil.isEmptyOrLength0(defaultValueMap.get(map.get("id")))){
                        map.put("defaultValue",defaultValueMap.get(map.get("id")));
                    }
                }
            }
        }

        JsonOpt.put("list",list);
        model.addAttribute("loadFormJson",formDesignEntityList.size()>0?StringUtil.escape(JSON.toJSONString(JsonOpt)):"");
       // model.addAttribute("loadFormJson",formDesignEntityList.size()>0?StringUtil.escape(JSON.toJSONString(list)):"");
        model.addAttribute("tempid",param.getOrDefault("tempid",""));
        model.addAttribute("dataid",param.getOrDefault("dataid",""));
        return "thymeleaf/devtools30/sysform/v_FormDesignPreview";
    }
    private Object FormatData(Object val){
        if(val==null)
            return val;

        if(val instanceof Timestamp){
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return df.format(val);
        }
        return val;
    }
}
